double = Proc.new do |*args|
  # 等价于 double = proc do |*args|
  args.map { |item| item * 2 }
end
p double.call(1, 2, 3)
p double[1, 2, 3]
p double.lambda?

double2 = lambda do |a, b, c|
  p [a * 2, b * 2, c * 2]
end
# p double2.call(1,2) #报错ArgumentError
p double2[1, 2, 3]

square = ->(a) { a ** 2 } # lambda表达式的简易写法
p square[5] #看着像数组，其实是lambda调用
p square.lambda?

fizz = Proc.new{|n| n%3 == 0}
buzz = Proc.new{|n| n%5 == 0}
fizzbuzz = Proc.new{|n| fizz[n] && buzz[n]}
puts fizz === 1 # proc === value 相当于执行proc块
puts fizz === 3
=begin
(1..100).each do |i|
  case i
  when fizzbuzz then puts "Fizz Buzz"
  when fizz then puts "Fizz"
  when buzz then puts "Buzz"
  else puts i
  end
end
=end

def my_collect(obj, &block)
  if obj.respond_to?('each')
    result = []
    obj.each do |item|
      if block
        result << block.call(item)
      else
        result << item
      end
    end
    result

  else
    puts "input #{obj} hasn't 'each' method"
  end
end
p my_collect([1,2,3])
p my_collect([1,2,3]){ |n| n**2 }
p my_collect(1)

to_class = :class.to_proc
p to_class.call("test") # 相当于调用了"test".class
p to_class.call(123) # 相当于调用量123.class
p to_class.call(2 ** 100)

method(:puts).to_proc.call(1)   # prints 1
[1, 2].each(&method(:puts))     # prints 1, 2

def accumulator
  total = 0
  Proc.new do |n|
    total += n
  end
end
acc = accumulator
p acc.call(1)
p acc.call(2)
p acc.call(3)
p acc.call(4)